
#include <windows.h>
#include <tchar.h>
#include <vld.h>
#include "Game.h"

const TCHAR*	WINDOW_CLASS	= _T("Heavy Reinforcements");
const TCHAR*	WINDOW_TITLE	= _T("Heavy Reinforcements");
const int		WINDOW_WIDTH	= 800;
const int		WINDOW_HEIGHT	= 600;
const BOOL		WINDOWED_MODE	= TRUE;

BOOL RegisterWindowClass(HINSTANCE hInstance);
HWND MakeWindow(HINSTANCE hInstance);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	MSG		msg;  //Generic message
	HWND	hWnd; //Window handle

	//Register the window class
	if (RegisterWindowClass(hInstance) == FALSE)
	{
		MessageBox(HWND_DESKTOP, _T("ERROR: Failed to register the window class."),
			WINDOW_TITLE, MB_OK | MB_ICONERROR);
		return -2;
	}

	//Create the window
	hWnd = MakeWindow(hInstance);
	if (hWnd == 0)
	{
		MessageBox( HWND_DESKTOP, _T("ERROR: Failed to create the Main Window."),
			WINDOW_TITLE, MB_OK | MB_ICONERROR);
		//	Unregister the window class
		UnregisterClass(WINDOW_CLASS, hInstance);
		return -3;
	}

	//Display the window
	ShowWindow(hWnd, nCmdShow);
	UpdateWindow(hWnd);

	//Initialize the game
	Game* pGame = Game::GetInstance();
	pGame->Initialize( hWnd, hInstance,
		WINDOW_WIDTH, WINDOW_HEIGHT, WINDOWED_MODE);

	//Enter main event loop
	while (true)
	{
		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
		{ 
			if (msg.message == WM_QUIT)
				break;
			//Translate accelerator keys
			TranslateMessage(&msg);
			//Send the message to the window proc
			DispatchMessage(&msg);
		}
		else
		{
			//Execute game frame
			if (pGame->Main() == false)
				PostQuitMessage(0);
		}
	}
	
	//Shut down the game
	pGame->Terminate();
	//Game::DeleteInstance();
	pGame = nullptr;

	//Unregister the window class
	UnregisterClass(WINDOW_CLASS, hInstance);

	//Quit
	return (int)(msg.wParam);
}


BOOL RegisterWindowClass(HINSTANCE hInstance)
{
	WNDCLASSEX	winClassEx;
	winClassEx.cbSize			= sizeof(winClassEx);
	winClassEx.style			= CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
	winClassEx.lpfnWndProc		= WindowProc;
	winClassEx.cbClsExtra		= 0;
	winClassEx.cbWndExtra		= 0;
	winClassEx.hInstance		= hInstance;
	winClassEx.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
	winClassEx.hIconSm			= NULL;
	winClassEx.hCursor			= LoadCursor(NULL, IDC_ARROW);
	winClassEx.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
	winClassEx.lpszMenuName		= NULL; 
	winClassEx.lpszClassName	= WINDOW_CLASS;
	//Register the window class
	return RegisterClassEx(&winClassEx);
}


HWND MakeWindow(HINSTANCE hInstance)
{
	DWORD dwWindowStyleFlags = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
	RECT rWindow;
	rWindow.left	= 0;
	rWindow.top		= 0;
	rWindow.right	= WINDOW_WIDTH;
	rWindow.bottom	= WINDOW_HEIGHT;
	AdjustWindowRectEx(&rWindow, dwWindowStyleFlags, FALSE, WS_EX_APPWINDOW);
	int nWindowWidth	= rWindow.right - rWindow.left;
	int nWindowHeight	= rWindow.bottom - rWindow.top;

	//Create the window
	return CreateWindowEx(
		WS_EX_APPWINDOW,									//Extended Style flags.
		WINDOW_CLASS,										//Window Class Name.
		WINDOW_TITLE,										//Title of the Window.
		dwWindowStyleFlags,									//Window Style Flags.
		(GetSystemMetrics(SM_CXSCREEN) - nWindowWidth)/2,	//Window Start Point (x, y). 
		(GetSystemMetrics(SM_CYSCREEN) - nWindowHeight)/2,	//Center the window over the desktop.
		nWindowWidth,										//Width of Window.
		nWindowHeight,										//Height of Window.
		HWND_DESKTOP,										//Handle to parent window.
		NULL,												//Handle to menu.
		hInstance,											//Application Instance.
		NULL);												//Creation parameters.
}


LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	//Handle message
	switch (msg)
	{
	case WM_CREATE: 
		{
		}
		break;

	case WM_DESTROY: 
		{
			PostQuitMessage(0);
		}
		break;

		//Ignore ALT pop up menu (system menu)
	case WM_SYSKEYUP:
	case WM_SYSCHAR:
		{
		}
		break;

		//ALT+F4
	case WM_CLOSE:
		{
			DestroyWindow(hWnd);			
		}
		break;

		//Gain/lose focus
	case WM_ACTIVATE:
		{
			if (LOWORD(wParam) != WA_INACTIVE)
			{
				//Gaining focus
			}
			else
			{
				//Losing focus
			}
		}
		break;

		//Ignore repaint
	case WM_PAINT:
		{
			PAINTSTRUCT	ps;
			HDC			hdc;
			//Start painting
			hdc = BeginPaint(hWnd,&ps);
			//End painting
			EndPaint(hWnd,&ps);
		}
		break;

	default:
		return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return 0;
}
